#include <float.h>
#include "array.h"

Array* create_array()
{
    Array * ay = (Array *)malloc(sizeof(Array));
    ay->max_size = DEFAULT_ARRAY_SIZE;
    ay->num_elements = 0;
    ay->elements = (double *)malloc(sizeof(double) * ay->max_size);
}

/* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */

double get_element(Array * ay, int index)
{
    if(index >= ay->num_elements)
    {
        printf("Error, %d is bigger than array size\n", index);
    }
    return ay->elements[index];
}

/* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */

void push_back(Array *ay, double value)
{
    int i;
    if(ay->num_elements >= ay->max_size)
    {
        // Increase the memory by 2, and copy the old values
        // to new memory locations
        ay->max_size *= 2;
        double *temp = (double *)malloc(sizeof(double) * ay->max_size);
        for(i = 0; i < ay->num_elements; i++)
        {
            temp[i] = ay->elements[i];
        }
        free(ay->elements);
        ay->elements = temp;
        ay->elements[ay->num_elements] = value;
    }
    else
    {
        ay->elements[ay->num_elements] = value;
    }

    ay->num_elements++;
}

/* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */

void free_array(Array *ay)
{
    if(ay != NULL)
    {
        if(ay->elements != NULL)
        {
            free(ay->elements);
        }
        free(ay);
    }
}

/* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */

int compar (const void * elem1, const void * elem2)
{
    if(*(double*)elem1 > *(double*)elem2) return 1;
    else if (*(double*)elem1 < *(double*)elem2) return -1;
    else return 0;
}

/* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */

void sort_elements(Array *ay)
{
    qsort(ay->elements, ay->num_elements, sizeof(double), compar);
}

/* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */

void compute_statistics
(
    Array *ay, 
    double *median,
    double *average,
    double *min,
    double *max
)
{
    double sum = 0.0;
    double min_val = DBL_MAX;
    double max_val = 0.0;

    sort_elements(ay);
    if(ay->num_elements % 2 == 0)
    {
        int upper = ay->num_elements/2;
        int lower = upper - 1;
        *median = (ay->elements[upper] + ay->elements[lower])/2.0;
    }
    else
    {
        int index = (ay->num_elements - 1)/2;
        *median = ay->elements[index];
    }

    int i; 
    for(i = 0; i < ay->num_elements; i++)
    {
        sum += ay->elements[i];
    }
    
    if(ay->num_elements > 0)
    {
        *average = sum/ay->num_elements;
    }
    else 
    {
        *average = sum;
    }
    *min = ay->elements[0];
    *max = ay->elements[ay->num_elements-1];
}


